package cn.icare.cms;

import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class AESUtil {
    //加密方式
    public static String KEY_ALGORITHM = "AES";
    //数据填充方式
    private final String algorithmStr = "AES/CBC/PKCS7Padding";


    //避免重复new生成多个BouncyCastleProvider对象，因为GC回收不了，会造成内存溢出
    //只在第一次调用decrypt()方法时才new 对象
    public static boolean initialized = false;


    //退款解密，算法/工作模式/填充方式
    private final  String ALGORITHM_MODE_PADDING="AES/ECB/PKCS5Padding";

    /**
     *
     * @param originalContent
     * @param encryptKey
     * @param ivByte
     * @return
     */
    public byte[] encrypt(byte[] originalContent, byte[] encryptKey, byte[] ivByte) {
        initialize();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec skeySpec = new SecretKeySpec(encryptKey, "AES");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(ivByte));
            byte[] encrypted = cipher.doFinal(originalContent);
            return encrypted;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * AES解密 用于小程序接口用于的敏感数据解密，需要小程序的向量(IV)的数据
     * 填充模式AES/CBC/PKCS7Padding
     * 解密模式128
     * @param content
     *            目标密文
     * @return
     * @throws Exception
     * @throws InvalidKeyException
     * @throws NoSuchProviderException
     */
    public byte[] decrypt(byte[] content, byte[] aesKey, byte[] ivByte) {
        initialize();
        try {
            Cipher cipher = Cipher.getInstance(algorithmStr);
            Key sKeySpec = new SecretKeySpec(aesKey, "AES");
            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * AES解密-用于微信退款回传的加密数据解密
     * @param base64Data base64加密数据
     * @param lowMad5Key MD5加密并转为小写的密钥字符串
     * @return
     */
    public String decrypt(String base64Data, String lowMad5Key) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
        SecretKeySpec key = new SecretKeySpec(lowMad5Key.getBytes(), KEY_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] decode = Base64Util.decode(base64Data);
        byte[] doFinal = cipher.doFinal(decode);
        return new String(doFinal,"utf-8");
    }

    /**BouncyCastle作为安全提供，防止我们加密解密时候因为jdk内置的不支持改模式运行报错。**/
    public static void initialize() {
        if (initialized)
            return;
        Security.addProvider(new BouncyCastleProvider());
        initialized = true;
    }

    // 生成iv
    public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
        AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
        params.init(new IvParameterSpec(iv));
        return params;
    }

    public static void main(String[] args)
    {

        try {
            String encodeData="09rGGgfTmB5SpnhTbjepQsDjGCTRWtiGADmt+EE2bTkKAwbdH/cCSZR3Q7wBuuaP2f67DdwApUJ3nx+DfroZUM6lNL1nsgRmcevvv4nYaN7A85aA49q65p1ELgbLzcLfiA+mbyY5OTHuQDf9KyZzSPC5tvm2WUZls+78kiXKUbqDcaCKonMy/yEkTUdSefRu8T4XVI6vTHReyuutBbyr8CeEG00tgIjSaSYfgZlBdpfzBipiSnzgvxK04FybyqnMVtg30TF0c50svjh8zFa4LC8Fh0YW2xUqdLemu3uQLqgtfhyLogPNGRAh7o2M+T/4lNrmdHVT1IMel0gtsZOrap3BL1SThOwvAhZHvxrd3MGp7VXAOaPzI9SfaL2G1BR78vqrjtAZxt+7jtw6DYyRXfzRb3v37FDgBz4ixlvijQwpiHnL+IF8dLOcBPJo71Jrgma+cnZAWIg818jk2Afi1kbinnJy/rUe9gJFaxgavtn8c+FboHzRPX5IprWm9W3/sxVvG4+yzxnswzssKNWj29M04FNgX0mPCyViDXbubFQW06ZTC6U08LqsSW0oiQCLltgdKzBmBfd42+0Dati4XZoc8agDv2skU3LqxmMs9sqvZiceNRXa/XpwthG1EEzUhEs6mCv6Huca3MNZAfb1o0sU2OIquzY8d6As1gRVC0YSMlCTtc1t81qn/aQ8HwKetrDobu2+iGBdDK4X2kAgz/78zu+UWkwIMRtlvzSSNfsALW6idGc0r0z01KgNxGBD0ES9AX7e6gLaY+l6HupIa4VLt8fg1JFND2kEOqSpFJmf9+TY3sNn59je2FrGP7KB2I376i3E1KDj/6v1JkXdbEhdo1Dq9aMQ4JuyqdGCeiWEtrS9/MpY5ApKe8+VYZAeRPnyM+OEYo5igrn5Tfp82M3IYnsPBA5WJrIgvMoqI+lVWKzkim4ARxLYDQDb+oo8EszgbGqPg6R3XsXwl7cJgUhsukpfBcnapTVJdiYXJEy3En/Y/pyw4DhX6RUmk5gjxKPAsN2mTIb2McsvoVhJzC5ZgZfh6SI6E0pxFmDOrs/nZjsnwtwrbFh3TtKLpidJxem7fR9vh/hfgpK1+0o4ig==";
            String lowMD5Key = MD5Util.MD5Encode("8862SJ6ZX9190V66BCJ42VV31K98KM31", "UTF-8").toLowerCase();
            String decodeData=new AESUtil().decrypt(encodeData,lowMD5Key);
            System.out.println("decodeData:"+decodeData);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }


    }
}
